﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Autofac;
using Downplay.Alchemy.Services;
using Orchard.Tests;
using Orchard.ContentManagement;
using Downplay.Alchemy.Events;

namespace Downplay.Science.Tests.Services {
    [TestFixture]
    public class AlchemyTests : DatabaseEnabledTestsBase {

        private IAlchemyService _alchemy;
        private IContentManager _contentManager;

        public override void Register(ContainerBuilder builder) {

            builder.RegisterType<AlchemyService>().As<IAlchemyService>();

            builder.RegisterType<Result1Overrider>().As<ICompositionProvider>();
            builder.RegisterType<Result2Builder>().As<ICompositionProvider>();

        }

        public override void Init() {
            base.Init();

            _alchemy = _container.Resolve<IAlchemyService>();
            _contentManager = _container.Resolve<IContentManager>();
        }

        [Test]
        public void EmitDefaultStringResult() {
            var foo = _alchemy.Compose().Factory<string>(context => "Foo").Go().Build<string>();
            Assert.That(foo, Is.EqualTo("Foo"));
        }

        [Test]
        public void EmitDefaultResult() {
            var foo = _alchemy.Compose().Factory<Result>(context => new Result() { Text = "Foo" }).Go().Build<Result>();
            Assert.That(foo.Text, Is.EqualTo("Foo"));
        }

        [Test]
        public void OverrideDefaultResult() {
            var result = _alchemy.Compose().Factory<Result1>(context => new Result1() { Text = "Base" }).Go().Build<Result1>();
            Assert.That(result.Text, Is.EqualTo("Overidden"));
        }

        [Test]
        public void ScopedOverride() {
            var result = _alchemy.Compose().Go();
            var result2_1 = result.Build<Result2>();
            result = _alchemy.Compose().Scope("Foo").Go();
            var result2_2 = result.Build<Result2>();
            Assert.That(result2_1.Text, Is.EqualTo("Result2"));
            Assert.That(result2_2.Text, Is.EqualTo("Result2Scoped"));
        }

        public class Result {
            public String Text { get; set; }
        }
        public class Result1 : Result { }
        public class Result2 : Result { }
        public class Result3 : Result { }

        public class Result1Overrider : ICompositionProvider {
            public void Subscribe(RootBuilder describe) {
                describe.Global(global => {
                    global.Factory<Result1>(context => new Result1() { Text = "Overidden" });
                });
            }
        }
        public class Result2Builder : ICompositionProvider {
            public void Subscribe(RootBuilder describe) {
                describe.Global(global => {
                    global.Factory<Result2>(context => new Result2() { Text = "Result2" });
                });
                describe.Scope("Foo", foo => {
                    foo.Factory<Result2>(context => new Result2() { Text = "Result2Scoped" });
                });
            }
        }

    }
}
